package com.easy.commons.utils;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.*;
import java.security.Key;
import java.util.Base64;

/**
 * @Packge com.easy.commons.utils
 * @Autor linNaibin
 * @Description
 * @Version 1.0
 * @Date 2021/1/12 17:40
 */
public class DESUtil {

    /**
     * 偏移变量，固定占8位字节
     */
    private final static String IV_PARAMETER = "12345678";

    /**
     * 密钥算法
     */

    private static final String ALGORITHM = "DES";

    /**
     * 加密/解密算法-工作模式-填充模式
     */

    private static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";

    /**
     * 默认编码
     */

    private static final String CHARSET = "utf-8";

    private static final char[] DIGITS = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c',
            'd', 'e', 'f'};

    public static String toString(byte[] data) {
        if (data == null) {
            return "null!";
        } else {
            int l = data.length;
            char[] out = new char[l << 1];
            int i = 0;

            for (int var4 = 0; i < l; ++i) {
                out[var4++] = DIGITS[(240 & data[i]) >>> 4];
                out[var4++] = DIGITS[15 & data[i]];
            }

            return new String(out);
        }
    }

    /**
     * 生成key
     *
     * @param password
     * @return
     * @throws Exception
     */
    private static Key generateKey(String password) throws Exception {

        DESKeySpec dks = new DESKeySpec(password.getBytes(CHARSET));

        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);

        return keyFactory.generateSecret(dks);

    }

    public static final String bytesToHex(byte[] buf, int off, int len) {
        char[] out = new char[len * 2];
        int i = 0;

        for (int var5 = 0; i < len; ++i) {
            int a = buf[off++];
            out[var5++] = DIGITS[a >>> 4 & 15];
            out[var5++] = DIGITS[a & 15];
        }

        return new String(out);
    }


    /**
     * DES加密字符串
     *
     * @param password 加密密码，长度不能够小于8位
     * @param data     待加密字符串
     * @return 加密后内容
     */
    public static byte[] encrypt(String password, String data) {

        if (password == null || password.length() < 8) {

            throw new RuntimeException("加密失败，key不能小于8位");

        }

        if (data == null)

            return null;

        try {

            Key secretKey = generateKey(password);

            // 实例化Cipher对象，它用于完成实际的加密操作
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

            // IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));

            //cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);

            // 用密钥初始化Cipher对象，设置为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);

            byte[] bytes = cipher.doFinal(data.getBytes(CHARSET));

            return bytes;
            // return new String(Base64.getEncoder().encode(bytes));

        } catch (Exception e) {

            e.printStackTrace();

            return null;

        }

    }

    /**
     * 16 进制展示
     *
     * @param password
     * @param data
     * @return
     */
    public static String encryptToHex(String password, String data) {

        byte[] result = encrypt(password, data);

        return bytesToHex(result, 0, result.length);
    }

    /**
     * DES解密字符串
     *
     * @param password 解密密码，长度不能够小于8位
     * @param data     待解密字符串
     * @return 解密后内容
     */
    public static String decrypt(String password, String data) {

        if (password == null || password.length() < 8) {

            throw new RuntimeException("解密失败，key不能小于8位");

        }

        if (data == null)

            return null;

        try {

            Key secretKey = generateKey(password);

            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

            //IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));

            cipher.init(Cipher.DECRYPT_MODE, secretKey);

            return new String(cipher.doFinal(Base64.getDecoder().decode(data.getBytes(CHARSET))), CHARSET);

        } catch (Exception e) {

            e.printStackTrace();

            return data;

        }

    }

    /**
     * DES加密文件
     *
     * @param srcFile  待加密的文件
     * @param destFile 加密后存放的文件路径
     * @return 加密后的文件路径
     */
    public static String encryptFile(String password, String srcFile, String destFile) {

        if (password == null || password.length() < 8) {

            throw new RuntimeException("加密失败，key不能小于8位");

        }

        try {

            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));

            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

            cipher.init(Cipher.ENCRYPT_MODE, generateKey(password), iv);

            InputStream is = new FileInputStream(srcFile);

            OutputStream out = new FileOutputStream(destFile);

            CipherInputStream cis = new CipherInputStream(is, cipher);

            byte[] buffer = new byte[1024];

            int r;

            while ((r = cis.read(buffer)) > 0) {

                out.write(buffer, 0, r);

            }

            cis.close();

            is.close();

            out.close();

            return destFile;

        } catch (Exception ex) {

            ex.printStackTrace();

        }

        return null;

    }

    /**
     * DES解密文件
     *
     * @param srcFile  已加密的文件
     * @param destFile 解密后存放的文件路径
     * @return 解密后的文件路径
     */

    public static String decryptFile(String password, String srcFile, String destFile) {

        if (password == null || password.length() < 8) {

            throw new RuntimeException("加密失败，key不能小于8位");

        }

        try {

            File file = new File(destFile);

            if (!file.exists()) {

                file.getParentFile().mkdirs();

                file.createNewFile();

            }

            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));

            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

            cipher.init(Cipher.DECRYPT_MODE, generateKey(password), iv);

            InputStream is = new FileInputStream(srcFile);

            OutputStream out = new FileOutputStream(destFile);

            CipherOutputStream cos = new CipherOutputStream(out, cipher);

            byte[] buffer = new byte[1024];

            int r;

            while ((r = is.read(buffer)) >= 0) {

                cos.write(buffer, 0, r);

            }

            cos.close();

            is.close();

            out.close();

            return destFile;

        } catch (Exception ex) {

            ex.printStackTrace();

        }

        return null;

    }

    public static void main(String[] args) {

        // String e =
        // "6cd56ec7c01fa399dcaba1c1bc334e20&2fb5f7f2ebc194c44957a95c95a3466515162ffd6e92656bfc7cbe911f286767a1f371c5a8b6f65f63ccdc9f0ed76679976bf0d192843ce528f13a0edf0d6d48c1b1cd91356b172f7a28fc225759761986ca9d41d07e2c75acd812e6085598f35825fef1b41a9dcfd0ff6595211babf7ee8d2d4f24ed7d3a02bc39b8ad1f14e159c5f889b27740bc7976df4ea575427ebac0132236a0c1dce41202f62aee8110c864d41f263dc3d3ec8b9f0caa3095745df39fd233f2c3c23a3a645b2241b487594d955f380c5ea545dd73e69fe8fcf59f9ed7d0242e329aaca0e7439df30e3dea5038569c9cc46fea14b46970eef7705900321ecc2cbc6637b1e5592d1c684ba38fc8f4a32612d4420d11c18cdd43463fbdc1e45ba08d66c277a8af9d5ae2b1c7881484d080611b69205b4c12c52e13296bab95e1e4d37928beddd2e916a5551d1d452ebbbff1a0473603536ecdea3fa01344162a7675c61e98db1447d3d5894baa26c8c93e9c4630fa5940da2ac302a511b6f26671e1909d404b0ae914af50c067a79f980c898a52f400fb30b38f14fea270c37fcab7adb8dee0c2bb7526a941e616d025bb938887eeed7fd86045a38bbc6f1dee3c4a4bb4be8062d0c66732";

        String j = "userName=mumu&passwordZxc123!";
        String result = encryptToHex("Zxc1234@1", "mumu");

        String result2 = decrypt("12345678",
                "cb70352afd2a94b0ce5e46199272668c&2fb5f7f2ebc194c44957a95c95a3466515162ffd6e92656bfc7cbe911f286767a1f371c5a8b6f65f63ccdc9f0ed76679976bf0d192843ce528f13a0edf0d6d48c1b1cd91356b172fe1a86afc336a5a7e8d832e7cbeeaf52bd0ff6595211babf7ee8d2d4f24ed7d3a02bc39b8ad1f14e159c5f889b27740bc7976df4ea575427ebac0132236a0c1dce41202f62aee8110c864d41f263dc3d3ec8b9f0caa309574a711131e81c8892556fb5d095ea45af7594d955f380c5ea545dd73e69fe8fcf59f9ed7d0242e329aaca0e7439df30e3dea5038569c9cc46fea14b46970eef7705900321ecc2cbc6637b1e5592d1c684ba38fc8f4a32612d4420d11c18cdd43463fbdc1e45ba08d66c277a8af9d5ae2b1c7881484d080611b69205b4c12c52e13296bab95e1e4d37928beddd2e916a5551d1d452ebbbff1a0473603536ecdea3fa01344162a7675c61e98db1447d3d5894baa26c8c93e9c4630fa5940da2ac302a511b6f26671e1909d404b0ae914af50c067a79f980c898a52f400fb30b38f14fea270c37fcab7adb8dee0c2bb7526a941e616d025bb938887eeed7fd86045a38bbc6f1dee3c4a4bb4be8062d0c66732");

        System.out.println(result);
        System.out.println(result2);

    }

}